# -*- coding:utf-8 -*-
# @Author:Liu Guoyang
# @Time  :2019/5/15 10:44
# @File  :link2.py


"""
链表：


assert断言：声明其布尔值必须为真的判定，如果发生异常就说明表达式为假。
eg:
    print(2 > 3)  # False
    assert 2 > 3  # AssertionError

raise抛出异常：raise 唯一的一个参数指定了要被抛出的异常。
            它必须是一个异常的实例或者是异常的类（也就是 Exception 的子类）。
eg：
    raise NameError('HiThere')

Traceback (most recent call last):
  File "D:/PythonProgram/python_rimi/section3/code/draft.py", line 16, in <module>
    raise NameError('HiThere')
NameError: HiThere

对象属性、类属性、静态属性

"""


class Node:
    def __init__(self, data):
        self.data = data
        self.next = None


class SingleLinkList:
    """单链表"""
    def __init__(self, node=None):
        self.head = node

    def isempty(self):
        """链表是否为空"""
        return self.head is None

    def length(self):
        """查看链表的长度"""
        pass

    def travel(self):
        """遍历整个链表"""
        cur = self.head

        while cur is not None:
            print(cur.data, end=" ")
            cur = cur.next

    def add(self, item):
        """链表头部添加元素， 头插法"""
        node = Node(item)
        node.next = self.head  # 先让新节点的next指向原头结点
        self.head = node  # 再把原头结点指向新节点

    def append(self, item):
        """链表尾部添加元素, 尾插法"""
        node = Node(item)

        if self.isempty():
            # 先判断原链表是否为空
            self.head = node  # 为空则让头结点指向这个心插入的结点

        else:
            cur = self.head

            while cur.next is not None:
                cur = cur.next

            cur.next = node

    def insert(self, pos, item):
        """指定位置添加元素"""
        node = Node(item)
        cur = self.head

        if pos == 0:
            self.add(item)

        else:
            count = 1
            while count < pos:  # pos=3
                cur = cur.next
                count += 1

            node.next = cur.next
            cur.next = node

    def search(self, item):
        cur = self.head

        while cur.next is not None:
            if cur.data == item:
                return True
            else:
                cur = cur.next

        return False

    def remove(self, item):
        """根据位置删除元素"""
        cur = self.head
        pre = None

        while cur is not None:
            if cur.data == item:
                # 先判断此节点是否为头节点
                if cur == self.head:
                    self.head = cur.next
                else:
                    pre.next = cur.next
                break
            else:
                pre = cur
                cur = cur.next

    def __len__(self):
        # cur游标，用来移动遍历节点
        cur = self.head
        # count记录数据
        count = 0

        while cur is not None:
            count += 1
            cur = cur.next

        return count

    def __iter__(self):
        return LinkIterator(self)

    def __abs__(self, number):
        """求绝对值"""
        if number >= 0:
            return number
        else:
            return -number

    def __contains__(self, item):
        for d in self:
            if d == item:
                return True
        return False

    def __setitem__(self, key, value):
        """根据索引修改元素值"""
        if self.isempty():
            print("This is linklist is NULL!")
        else:
            if key >= 0:
                try:
                    assert key <= len(self) - 1

                except Exception:
                    print("Index is out of range!")
                    return ""

                cur = self.head
                count = 0

                while count < key:
                    cur = cur.next
                    count += 1

                cur.data = value
            else:
                try:
                    assert key >= -len(self)
                except Exception:
                    print("Index is out of range!")
                    return ""

                cur = self.head
                count = 0
                key = len(self) - abs(key)

                while count < key:
                    cur = cur.next
                    count += 1

                cur.data = value

    def __getitem__(self, item):
        assert item <= len(self) - 1
        cur = self.head.next
        while item:
            cur = cur.next
            item -= 1

        return cur.data

    def __add__(self, other):
        if self.isempty():
            new_list = other

        else:
            cur = self.head

            while cur.next is not None:
                cur = cur.next

            cur.next = other.head
            new_list = self

        return new_list


class LinkIterator:
    def __init__(self, link):
        self._node_ptr = link.head

    def __next__(self):
        self._node_ptr = self._node_ptr.next
        if self._node_ptr is None:
            raise StopIteration
        data = self._node_ptr.data
        return data


if __name__ == '__main__':
    # ll = SingleLinkList()
    # print(ll.isempty())
    # print(len(ll))

    # ll.append(1)
    # print(ll.isempty())
    # print(ll.length())

    # ll.append(2)
    # ll.add(8)
    # ll.append(3)
    # ll.append(4)
    # ll.append(5)
    # ll.append(6)

    # ll.insert(0, 100)
    # ll.insert(3, 100)
    #
    # ll.remove(5)

    # ll[2] = 55
    # ll[3] = 200
    # ll[-1] = 500
    # ll[0] = 999
    #
    # ll.travel()
    #
    # print(200 in ll)

    list1 = SingleLinkList()
    list2 = SingleLinkList()

    list1.append(1)
    list1.append(2)
    list1.append(3)
    # 1 2 3

    list2.append(4)
    list2.append(7)
    list2.append(5)
    list2.append(6)
    # 4 7 5 6

    list1.travel()
    print()
    list2.travel()
    print()

    list3 = list1 + list2
    # list3.travel()

    list2 += list1
    list2.travel()



